/*
 * Copyright 2009 Eat Local Food, LLC
 * Copyright (c) 2007 osCommerce (this file was written after
 * code review of osCommerce).
 *
 * This file is part of gwtCommerce.
 *
 * gwtCommerce is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * gwtCommerce is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with gwtCommerce.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.elf.gwt.common.client.model;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONValue;

/**
 *  
 */
public class AccountModel extends AbstractModel
{
	protected String historyAction;
	protected String title;
	protected List<AddressModel> addresses;
	protected Date dateOfBirth;
	protected AddressModel defaultAddress;
	protected AddressModel editAddress;
	protected String emailAddress;
	protected String fax;
	protected String firstname;
	protected String gender;
	protected int id;
	protected String lastname;
	protected boolean newsletter;
	protected String session;
	protected String telephone;
	protected boolean wholesale;
	protected String password;
	protected String captchaCode;
	protected String captchaSession;
	protected AccountMetaModel accountMetaModel;
	protected CartModel cartModel = null;
	protected int errorCode;
	protected List<String> roles;
	
	public AccountModel(CartModel cartModel)
	{
		update();
		this.cartModel = cartModel;
	}
	public AccountModel()
	{
		update();
	}

	public void update(JSONObject jsonObject)
	{
		update();

		id = convertToInteger(jsonObject, "id");
		session = convertToString(jsonObject, "session");
		gender = convertToString(jsonObject, "gender");
		firstname = convertToString(jsonObject, "firstname");
		lastname = convertToString(jsonObject, "lastname");
		dateOfBirth = convertToDate(jsonObject, "dob");
		emailAddress = convertToString(jsonObject, "email_address");
		telephone = convertToString(jsonObject, "telephone");
		fax = convertToString(jsonObject, "fax");
		newsletter = convertToBoolean(jsonObject, "newsletter");
		wholesale = convertToBoolean(jsonObject, "wholesale");
		errorCode = convertToInteger(jsonObject, "error_code");
		
		buildAddresses(jsonObject);
		buildRoles(jsonObject);
	}

	public void update(JSONObject jsonObject, AccountMetaModel accountMetaModel)
	{
		update(jsonObject);
		buildCart(jsonObject, accountMetaModel);
	}

	public void update()
	{
		this.id = 0;
		this.session = "";
		this.gender = "";
		this.firstname = "";
		this.lastname = "";
		this.dateOfBirth = null;
		this.emailAddress = "";
		this.telephone = "";
		this.fax = "";
		this.newsletter = false;
		this.wholesale = false;
		this.addresses = new ArrayList<AddressModel>();
		if (defaultAddress != null)
		{
			String country = defaultAddress.getCountry();
			defaultAddress.update();
			defaultAddress.setDefaultAddress(true);
			defaultAddress.setCountry(country);
		}
		this.errorCode = 0;
		this.roles = new ArrayList<String>();
	}

	protected void buildRoles(JSONObject jsonObject)
	{
		roles.clear();

		try {
			JSONValue rolesValue = jsonObject.get("roles");
			if (rolesValue != null)
			{
				JSONArray jsonArray;
				if ((jsonArray = rolesValue.isArray()) != null)
				{

					int sz = jsonArray.size();		
					for (int i = 0; i < sz; i++)
					{
						JSONValue jsonValue = jsonArray.get(i);
						JSONObject jsonAObject;
						if ((jsonAObject = jsonValue.isObject()) != null)
						{
							String name = convertToString(jsonAObject, "name");
							roles.add(name);
						}
					}
				}
			}
		}
		catch (Exception e) {}
	}

	protected void buildAddresses(JSONObject jsonObject)
	{
		getAddresses().clear();

		try {
			JSONValue addressValue = jsonObject.get("addresses");

			if (addressValue != null)
			{
				JSONArray jsonArray;
				if ((jsonArray = addressValue.isArray()) != null)
				{

					int sz = jsonArray.size();		
					for (int i = 0; i < sz; i++)
					{
						JSONValue jsonValue = jsonArray.get(i);
						JSONObject jsonAObject;
						if ((jsonAObject = jsonValue.isObject()) != null)
						{
							AddressModel addressModel = new AddressModel(jsonAObject);
							addAddress(addressModel);
							if (addressModel.isDefaultAddress())
							{
								setDefaultAddress(addressModel);
							}
						}
					}
				}
			}
		}
		catch (Exception e) {}
	}

	protected void buildCart(JSONObject jsonObject, AccountMetaModel accountMetaModel)
	{
		List<DetailedProductModel> cartProductModels = new ArrayList<DetailedProductModel>();

		try {
			JSONValue cartValue = jsonObject.get("cart");

			if (cartValue != null)
			{
				JSONArray jsonArray;
				if ((jsonArray = cartValue.isArray()) != null)
				{
					int sz = jsonArray.size();		
					for (int i = 0; i < sz; i++)
					{
						JSONValue jsonValue = jsonArray.get(i);
						JSONObject jsonCObject;
						if ((jsonCObject = jsonValue.isObject()) != null)
						{
							DetailedProductModel cartProductModel = 
								new DetailedProductModel(jsonCObject, accountMetaModel.getCartMetaModel().getImageWidthMax(), accountMetaModel.getCartMetaModel().getImageHeightMax());
							cartProductModel.setCartQuantity(cartProductModel.getCartQuantity());
							cartProductModel.setCartQuantityMax(accountMetaModel.getCartMetaModel().getCartQuantityMax());
							cartProductModels.add(cartProductModel);
						}
					}
					if (cartModel != null) {
						cartModel.setProducts(cartProductModels);
						cartModel.updateProductPrices();
						cartModel.setUploadCartRequired(false);
					}
				}
			}
		}
		catch (Exception e) {GWT.log("AccountModel.buildCart", e);}
	}

	public void addAddress(AddressModel address) {
		this.addresses.add(address);
	}

	public List<AddressModel> getAddresses() {
		return addresses;
	}

	public AddressModel getAddressById(int id) {
		for (Iterator<AddressModel> iter = addresses.iterator(); iter.hasNext(); )
		{
			AddressModel address = iter.next();
			if (address.getId() == id)
				return address;
		}
		return null;
	}

	public List<String> getRoles() {
		return roles;
	}

	public Date getDateOfBirth() {
		return dateOfBirth;
	}

	public AddressModel getDefaultAddress() {
		return defaultAddress;
	}

	public String getEmailAddress() {
		return emailAddress;
	}

	public String getFax() {
		return fax;
	}

	public String getFirstname() {
		return firstname;
	}

	public String getGender() {
		return gender;
	}

	public int getId() {
		return id;
	}

	public String getLastname() {
		return lastname;
	}

	public String getSession() {
		return session;
	}

	public String getTelephone() {
		return telephone;
	}

	public boolean isNewsletter() {
		return newsletter;
	}

	public boolean isWholesale() {
		return wholesale;
	}

	public void setDefaultAddress(AddressModel defaultAddress) {
		this.defaultAddress = defaultAddress;
	}

	public void setId(int id) {
		this.id = id;
	}

	public void setSession(String session) {
		this.session = session;
	}

	public void setAddresses(List<AddressModel> addresses) {
		this.addresses = addresses;
	}

	public void setDateOfBirth(Date dateOfBirth) {
		this.dateOfBirth = dateOfBirth;
	}

	public void setEmailAddress(String emailAddress) {
		this.emailAddress = emailAddress;
	}

	public void setFax(String fax) {
		this.fax = fax;
	}

	public void setFirstname(String firstname) {
		this.firstname = firstname;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public void setLastname(String lastname) {
		this.lastname = lastname;
	}

	public void setNewsletter(boolean newsletter) {
		this.newsletter = newsletter;
	}

	public void setTelephone(String telephone) {
		this.telephone = telephone;
	}

	public void setWholesale(boolean wholesale) {
		this.wholesale = wholesale;
	}

	public AddressModel getEditAddress() {
		return editAddress;
	}

	public void setEditAddress(AddressModel editAddress) {
		this.editAddress = editAddress;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}


	public AccountMetaModel getAccountMetaModel() {
		return accountMetaModel;
	}

	public void setAccountMetaModel(AccountMetaModel accountMetaModel) {
		this.accountMetaModel = accountMetaModel;
	}

	public String getHistoryAction() {
		return historyAction;
	}

	public void setHistoryAction(String historyAction) {
		this.historyAction = historyAction;
	}

	public String getCaptchaCode() {
		return captchaCode;
	}

	public void setCaptchaCode(String captchaCode) {
		this.captchaCode = captchaCode;
	}

	public String getCaptchaSession() {
		return captchaSession;
	}

	public void setCaptchaSession(String captchaSession) {
		this.captchaSession = captchaSession;
	}

	public int getErrorCode() {
		return errorCode;
	}

	public void setErrorCode(int errorCode) {
		this.errorCode = errorCode;
	}
	
	public boolean isAdministrator() {
		boolean admin = false;
		for (String role : roles) {
			if (role.toLowerCase().equals("administrator")) {
				admin = true;
				break;
			}
		}
		return admin;
	}
}
